<!--
 * @Author: Xujianchen
 * @Date: 2025-01-16 09:20:07
 * @LastEditors: Xujianchen
 * @LastEditTime: 2025-01-22 15:13:01
 * @Description: 动态el-form表单
-->
<template>
  <el-form
    ref="formRef"
    v-bind="bindValue"
    :model="formData"
    :rules="formRules"
  >
    <slot name="header" />
    <template v-if="!slots.default">
      <form-item
        v-model="formData"
        :items="dynamicItems"
        @change="(value) => handleChange(value, item)"
      />
    </template>
    <slot v-else />
    <slot name="footer" />
  </el-form>
</template>

<script setup>
import { ElMessage } from 'element-plus'
import FormItem from './form-item'

const props = defineProps({ items: Array })
const emit = defineEmits(['change'])

const attrs = useAttrs()
const slots = useSlots()

const formRef = ref(null)
const formData = ref(initValue())
const dynamicItems = ref(props.items)
const formRules = ref(attrs?.rules || {})
const instance = getCurrentInstance()

const bindValue = computed(() => ({
  labelWidth: 80,
  labelPosition: 'left',
  ...attrs,
}))

onMounted(() => {
  const formInstance = formRef.value
  for (const key in formInstance) {
    instance.exposed[key] = formInstance[key]
  }
})

// 初始化formData数据
function initValue() {
  if (slots.default || attrs?.model) {
    return attrs?.model || {}
  }

  return props.items.reduce((data, item) => {
    data[item.prop] = item.value ?? null
    return data
  }, {})
}

// 获取表单值
function getValues() {
  return formData.value
}

// 增加表单项
function addItem(item) {
  if (dynamicItems.value.some((i) => i.prop === item.prop)) {
    console.warn(`Item with prop ${item.prop} already exists.`)
    return ElMessage.warning(`Item with prop ${item.prop} already exists.`)
  }

  dynamicItems.value.push(item)
  formData.value[item.prop] = item.value ?? null
}

// 移除表单项
function removeItem(prop) {
  const itemsValue = dynamicItems.value
  if (!itemsValue.length) {
    return console.warn('No items to remove.')
  }

  const index = itemsValue.findIndex((item) => item.prop === prop)
  if (index === -1) {
    console.warn(`Item with prop ${prop} does not exist.`)
    return ElMessage.warning(`Item with prop ${prop} does not exist.`)
  }

  delete formData.value[prop]
  dynamicItems.value.splice(index, 1)
}

function setRules(rules) {
  formRules.value = rules
}

function handleChange(value, item) {
  emit('change', { value, item, formData: formData.value })
}

defineExpose({
  addItem,
  removeItem,
  getValues,
  setRules,
})
</script>
